<template>
  <div class="un-flow-user-wrap">
    <el-radio-group v-model="ruleType" :disabled="disabled">
      <el-radio
        v-for="dict in typeList"
        :key="parseInt(dict.value)"
        :label="dict.value"
        >{{ dict.label }}</el-radio
      >
    </el-radio-group>
    <div v-if="ruleType">
      <treeselect
        v-if="typeConfigMap[ruleType].isTree"
        v-model="typeConfigMap[ruleType].selected"
        :options="typeConfigMap[ruleType].data"
        multiple
        flat
        :defaultExpandLevel="3"
        placeholder="请选择"
        :normalizer="normalizer"
        :disabled="disabled"
        @input="onChange"
      />
      <el-select
        v-else
        v-model="typeConfigMap[ruleType].selected"
        multiple
        :multiple-limit="typeConfigMap[ruleType].limit"
        clearable
        style="width: 100%"
        filterable
        placeholder="请选择，支持搜索"
        :filter-method="userFilter"
        :disabled="disabled"
        @change="onChange"
      >
        <el-option
          v-for="item in typeConfigMap[ruleType].filtered"
          :key="parseInt(item.id)"
          :label="item.name"
          :value="parseInt(item.id)"
        />
      </el-select>
    </div>
    <el-select
      v-else
      value=""
      multiple
      clearable
      style="width: 100%"
      filterable
      placeholder="请先选择数据类型"
      :disabled="disabled"
    >
    </el-select>
  </div>
</template>

<script>
import { getDictDatas } from "@/utils/dict";
import request from "@/utils/request";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";

export default {
  name: "UnFlowUser",
  inheritAttrs: false,

  components: {
    // 按需加载
    Treeselect,
  },
  props: {
    value: {
      type: Object,
      default() {
        return {
          ruleType: "",
          selected: [],
        };
      },
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    typeList: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
      ruleType: "",
      // 设置 ruleType 对应的数据类型
      typeConfigMap: {
        /* 10: {
          data: [],
          isTree: false,
          selected: [],
          filtered: [],
          loaded: false,
          api: "",
          limit: 0
        }, */
        // 上面的映射关系需要从接口获取，才能做到不动代码，自由扩展
      },
    };
  },
  watch: {
    ruleType(val) {
      if (!this.typeConfigMap[val]) {
        this.setTypeConfig(val);
      }
      this.getData(val);
      this.emitInput(val, this.typeConfigMap[val].selected);
    },
    value: {
      handler(val) {
        this.setDefaultValue(val);
      },
      deep: true,
    },
    typeList: {
      handler(list) {
        this.setTypeToOptions(list);
        if (this.value) {
          this.getData(this.value.ruleType);
        }
      },
      deep: true,
    },
  },
  created() {
    this.setTypeToOptions(this.typeList);
    this.setDefaultValue(this.value);
  },
  mounted() {
    if (this.value) {
      this.getData(this.value.ruleType);
    }
  },
  methods: {
    emitInput(type, selected) {
      this.$emit("input", {
        ruleType: type,
        selected: selected,
      });
    },
    setDefaultValue(val) {
      if (val) {
        this.ruleType = val.ruleType;
        this.setTypeConfig(val.ruleType);
        this.typeConfigMap[val.ruleType].selected = [...(val.selected || [])];
      } else {
        this.ruleType = "";
      }
    },
    setTypeConfig(ruleType) {
      if (!this.typeConfigMap[ruleType]) {
        const currType = this.typeList.find(({ value }) => value === ruleType);
        this.typeConfigMap[ruleType] = {
          data: [],
          isTree: false,
          selected: [],
          filtered: [],
          loaded: false,
          api: currType ? currType.api : "",
          limit: 0,
        };
      }
    },
    setTypeToOptions(typeList) {
      const typeConfigMap = { ...this.typeConfigMap };
      for (let i = 0; i < typeList.length; i++) {
        const { value, api, limit } = typeList[i];
        if (!typeConfigMap[value]) {
          typeConfigMap[value] = {
            data: [],
            isTree: false,
            selected: [],
            filtered: [],
            loaded: false,
            api,
            limit,
          };
        } else {
          typeConfigMap[value].api = api;
          typeConfigMap[value].limit = limit;
        }
        // 设置初始值
        if (this.value && this.value.ruleType === value) {
          typeConfigMap[value].selected = this.value.selected || [];
        }
      }
      this.typeConfigMap = typeConfigMap;
    },
    getData(ruleType) {
      const currTypeConfig = this.typeConfigMap[ruleType];
      if (currTypeConfig && !currTypeConfig.loaded) {
        const { api } = currTypeConfig;
        if (api.indexOf("/") !== -1) {
          request({ url: api, method: "get" }).then(({ data }) => {
            this.typeConfigMap[ruleType].loaded = true;
            this.formatData(ruleType, data);

            // 普通 select 下拉框，进行截断
            if (!this.typeConfigMap[ruleType].isTree) {
              this.userFilter();
            }
          });
        } else if (getDictDatas(api).length) {
          const data = getDictDatas(api);

          this.typeConfigMap[ruleType].loaded = true;
          this.formatData(ruleType, data);
          // 普通 select 下拉框，进行截断
          if (!this.typeConfigMap[ruleType].isTree) {
            this.userFilter();
          }
        }
      }
    },
    // 格式化树形数据的下拉框
    normalizer(node) {
      return {
        id: node.id,
        label: node.name,
        children: node.children,
      };
    },
    /* 模糊搜索下数据量过大，截断 */
    userFilter(query = "") {
      const { data } = this.typeConfigMap[this.ruleType];
      let arr = [...data];
      if (query) {
        arr = data.filter((item) => {
          return item.name.includes(query) || String(item.id) == query;
        });
      }
      this.typeConfigMap[this.ruleType].filtered =
        arr.length > 100 ? arr.slice(0, 100) : arr;
    },
    /* 统一数据格式 */
    formatData(ruleType, data) {
      const d = [];
      let isTree = false;
      for (let i = 0; i < data.length; i++) {
        const { id, value, name, nickname, label, parentId } = data[i];
        const currData = {
          id: value || id,
          name: label || nickname || name,
        };
        if (parentId !== undefined && parentId !== null && parentId !== "") {
          isTree = true;
          currData.parentId = parentId;
        }
        d.push(currData);
      }
      this.typeConfigMap[ruleType].isTree = isTree;
      this.typeConfigMap[ruleType].data = isTree
        ? [...this.handleTree(d, "id")]
        : d;
    },
    onChange(vals) {
      this.emitInput(this.ruleType, vals);
    },
  },
};
</script>

<style lang="scss">
.un-flow-user-wrap {
  .el-radio-group {
    margin-bottom: 20px;
  }
  .el-radio {
    min-width: 100px;
    margin: 10px 20px 0 0;
  }
  .vue-treeselect {
    line-height: 1.5;
  }
}
</style>
